#include "threadCache.h"
#include "pageCache.h"


void* threadCache::allocate(size_t size) {
	assert(size <= MAX_SIZE);

	size_t alignNum = alignSize::align(size);
	size_t index = alignSize::index(size);

	if (!_threadList[index].empty()) {
		return _threadList[index].pop();
	}
	else {
		return fetchOfcentralCache(index, alignNum);
	}
}

void* threadCache::fetchOfcentralCache(size_t index, size_t alignNum) {
	size_t nPage = min(_threadList[index].getMaxSize(), alignSize::numOfSize(alignNum));
	
	if (_threadList[index].getMaxSize() == nPage) {
		++_threadList[index].getMaxSize();
	}

	void* start = nullptr; 
	void* end = nullptr;
	size_t getNum = centralCache::getCentralCache()->fetchOfCentral(start, end, nPage, index, alignNum);
	
	if (getNum == 1) {
		assert(start == end);
	}
	else {
		_threadList[index].pushRange(next(start), end, getNum - 1);
	}
	return start;
}

void threadCache::dellocate(void* ptr, size_t size) {
	assert(ptr);
	assert(size <= MAX_SIZE);

	size_t index = alignSize::index(size);
	_threadList[index].push(ptr);

	if (_threadList[index].size() >= _threadList[index].getMaxSize()) {
		returnCentralCache(_threadList[index], size);
	}
}

void threadCache::returnCentralCache(freeList& threadList, size_t size) {
	assert(!threadList.empty());

	void* start = nullptr;
	void* end = nullptr;
	threadList.popRange(start, end, threadList.getMaxSize());

	centralCache::getCentralCache()->releaseThreadCacche(start, size);
}